#include <stdio.h>
#include <stdlib.h>
#include <error.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sys/epoll.h>

#include "hzqSocket.h"
#include "ringBuffer.h"
#include "hzqFormat.h"
#include "hzqThreadPool.h"

//处理的图片大小有800K以上，且有8张，这里定义100k
#define RING_BUFFER_SIZE 1024*100

int g_sockfd_arr[128][2];   //第一个元素为host1与device连接的套接字句柄
                            //第二个元素为对应device与host2的连接句柄
HANDLE hRingBuf = NULL;
static int pthread_num = 0;
//static thread_pool *s_pool=NULL;

void *writeTORingBuffer(void *arg), *readFromRingBuffer(void *arg);

int main(int argc,char *argv[])
{
    int i=0;
    if(argc<3){
        printf("%s [host2 port] [local port]\n",argv[0]);
        exit(0);
    }
    /* 0.初始化线程池 */
    //s_pool = malloc(sizeof(thread_pool));
	//init_pool(s_pool,MAX_ACTIVE_THREADS);

    /* 1.初始化ring_buffer */
    hRingBuf=ringBuf_init(RING_BUFFER_SIZE);

    /* 2.创建一个线程循环去读ring_buffer */
    pthread_t tid_read;
    if(pthread_create(&tid_read, NULL,readFromRingBuffer, NULL) != 0){
        perror("create threads error");
    }

    /* 3.创建TCP服务,等待接收host1传输文件 */
    int servfd = -1;
    int epfd = creatEpollServer(&servfd,atoi(argv[2]));
    assert("epfd != -1");

    /* 4.创建事件 */
    struct epoll_event events[OPEN_MAX],ev;

    /* 5.等待事件 */
    while(1){
        int nfd = epoll_wait(epfd,events,current_connect+1,-1);
        for(i=0;i<nfd;i++){
            /* 如果是servfd可读，即有新的连接，服务器处于SYN_RCVD状态 */
            if(events[i].data.fd == servfd)
            {
                /* 接受连接，同时发起一个与host2的连接，两个连接的句柄存入二维数组以建立映射关系 */
                int host1_device = epollAccept(epfd,servfd);
                int host2_device = connect_serv("127.0.0.1",atoi(argv[1]));
                assert(host2_device!=-1);
                g_sockfd_arr[host1_device%128][1] = host2_device;
                printf("host1_device %d,host2_device %d\n",host1_device,host2_device);
            }
            else if(events[i].events&EPOLLIN)//如果是可读事件
            {
                pthread_t tid;
                if(pthread_create(&tid, NULL,writeTORingBuffer, (void *)(ulong)events[i].data.fd) != 0){
                    perror("create threads error");
                }
                pthread_join(tid,NULL);
                //add_task(s_pool,writeTORingBuffer,(void *)(ulong)events[i].data.fd);
                //add_task(s_pool,readFromRingBuffer,NULL);
            }
            else if(events[i].events&EPOLLRDHUP)//如果对端关闭连接
            {
                printf("a user closed\n");
                epoll_ctl(epfd,EPOLL_CTL_DEL,events[i].data.fd,&ev);
                close(events[i].data.fd);
                current_connect--;
                events->data.fd = -1;
            }else{
                printf("fd = %d\n",events[i].data.fd);
                printf("unknow error\n");
            }
        }
    }
    //destroy_pool(s_pool);
    pthread_join(tid_read,NULL);
    ringBuf_destroy(&hRingBuf);
    exit(0);
}
//读取host1发送的数据并写入环形buffer
void *writeTORingBuffer(void *arg)
{
    //printf("pthread_num = %d\n",++pthread_num);
    unsigned short cmd_num = 0;
    unsigned int packet_len = 0;
    char send_cmd[maxMessageSize+6];
    bzero(send_cmd,maxMessageSize+6);

    int r = Read((int)(ulong)arg, send_cmd+6, 6);
    head_analyze((char *)(send_cmd+6),&cmd_num,&packet_len);
    if(cmd_num == e_msgEndFile){
        Write((int)(ulong)arg,send_cmd+6,6);
        close((int)(ulong)arg);
        printf("end of the file\n");
        return NULL;
    }
    r = Read((int)(ulong)arg, send_cmd+12, packet_len);
    package_head((unsigned char*)send_cmd,(short)(ulong)arg,packet_len+6);

    ringBuf_write(hRingBuf,(unsigned char *)send_cmd,r+12);
    //printf("pthread_num = %d\n",--pthread_num);
    return NULL;
}
//读取环形buffer的内容并发送给host2
void *readFromRingBuffer(void *arg)
{
    printf("pthread_num = %d\n",++pthread_num);
    unsigned short sockfd;
    unsigned int packet_len;
    unsigned char arr_head[6];
    char send_cmd[maxMessageSize];

    while(1)
    {
        ringBuf_read(hRingBuf,arr_head,6);
        head_analyze((char *)arr_head,&sockfd,&packet_len);
        ringBuf_read(hRingBuf,(unsigned char *)send_cmd,packet_len);
        Write(g_sockfd_arr[sockfd][1],send_cmd,packet_len);
    }
    printf("pthread_num = %d\n",--pthread_num);
    return NULL;
}